/*
 * Connection.cpp
 *
 *  Created on: Jun 13, 2013
 *      Author: ken
 */

#include "Connection.hpp"
#include "Logger.hpp"
#include <arpa/inet.h>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>

#include "openssl/ssl.h"
#include "openssl/err.h"

Connection::Connection(){
	sd = 0;
}

Connection::~Connection(){
	close(sd);
}

int Connection::createConnection(std::string IP, std::string port){
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;

	//check ip
	if ((signed) (addr.sin_addr.s_addr = inet_addr(IP.c_str())) == -1) {
		Logger::getInstance().log("Ip is not valid");
		return(-1);
	}

	//check port
	if ((addr.sin_port = htons(std::atoi(port.c_str()))) == 0) {
		Logger::getInstance().log("Port is not valid");
		return(-1);
	}

	//make socket
	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		std::perror("Cannot make socket");
		return(-1);
	}

	//connect to socket
	if ((connect(sd, (struct sockaddr*) &addr, sizeof(addr))) != 0) {
		perror("Can't connect");
		return(-1);
	}
	return sd;
}

//TODO not working yet, no return bio,getting http file from a server instead.
BIO Connection::createSSLConnection(std::string IP, std::string port){
	BIO * bio;
	SSL * ssl;
	SSL_CTX * ctx;

	Logger::getInstance().log("1");
	SSL_library_init();
	int p;

	char * request = "GET / HTTP/1.1\x0D\x0AHost: www.verisign.com\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A";
	char r[1024];

	Logger::getInstance().log("2");
	/* Set up the library */
	ERR_load_BIO_strings();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();

	Logger::getInstance().log("3");
	/* Set up the SSL context */
	ctx = SSL_CTX_new(SSLv23_client_method());
	Logger::getInstance().log("4");

	/* Load the trust store*/
	if (!SSL_CTX_load_verify_locations(ctx, "/home/ken/workspace/wxLinuxClient/TrustStore.pem", NULL)) {
		Logger::getInstance().log("4.1");
		fprintf(stderr, "Error loading trust store\n");
		ERR_print_errors_fp(stderr);
		SSL_CTX_free(ctx);
		//return 0;
	}
	Logger::getInstance().log("5");
	/* Setup the connection */
	bio = BIO_new_ssl_connect(ctx);
	Logger::getInstance().log("6");

	/* Set the SSL_MODE_AUTO_RETRY flag */
	BIO_get_ssl(bio, &ssl);
	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
	Logger::getInstance().log("7");

	/* Create and setup the connection */
	//BIO_set_conn_ip(IP);
	//BIO_set_conn_port(port);
	BIO_set_conn_hostname(bio, "www.verisign.com:https");
	Logger::getInstance().log("8");

	if (BIO_do_connect(bio) <= 0) {
		fprintf(stderr, "Error attempting to connect\n");
		ERR_print_errors_fp(stderr);
		BIO_free_all(bio);
		SSL_CTX_free(ctx);
		//return 0;
	}
	Logger::getInstance().log("9");

	/* Check the certificate
	if (SSL_get_verify_result(ssl) != X509_V_OK) {
		fprintf(stderr, "Certificate verification error: %i\n",
				SSL_get_verify_result(ssl));
		BIO_free_all(bio);
		SSL_CTX_free(ctx);
		//return 0;
	}*/
	Logger::getInstance().log("10");

	/* Send the request */
	BIO_write(bio, request, strlen(request));
	Logger::getInstance().log("11");

	/* Read in the response */
	for (;;) {
		p = BIO_read(bio, r, 1023);
		if (p <= 0)
			break;
		r[p] = 0;
		printf("%s", r);
	}

	/* Close the connection and free the context */
	BIO_free_all(bio);
	SSL_CTX_free(ctx);
}
